home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / dtl / dt2dv.c < prev    next >
C/C++ Source or Header  |  1995-02-28  |  55KB  |  2,490 lines

  1. /* dt2dv - convert human-readable "DTL" file to DVI format
  2.          - this is intended to invert dv2dt version 0.5.*.
  3.    - version 0.5.3 - 16:54 GMT +11  Wed 1 March 1995
  4.      (this version uses fseek to move about in output DVI file)
  5.    - Geoffrey Tobin    ecsgrt@luxor.latrobe.edu.au
  6.    - patch:  Michal Tomczak-Jaegermann    ntomczak@vm.ucs.ualberta.ca
  7.    - Reference:  "The DVI Driver Standard, Level 0",
  8.                  by  The TUG DVI Driver Standards Committee.
  9.                  Appendix A, "Device-Independent File Format".
  10. */
  11.  
  12. /* unix version; read from stdin, write to stdout, by default. */
  13.  
  14. #include <ctype.h>
  15. #include <errno.h>
  16. #include <signal.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20.  
  21. #include "dtl.h"
  22.  
  23. /* maximum number of characters in a DTL input line */
  24. #define MAXLINE  1024
  25.  
  26. /* input line */
  27. typedef struct
  28. {
  29.   size_t next;  /* position in buf of next character to read */
  30.   size_t len;  /* number of characters in buf */
  31.   size_t max;  /* capacity of buf */
  32.   char * buf;  /* line buffer */
  33. } Line;
  34.  
  35. char linebuf[MAXLINE+1];
  36.  
  37. Line dtl_line = {0, 0, MAXLINE, linebuf};
  38.  
  39. /* a DTL token either is:
  40.      a quoted string (admitting an escape character),
  41.      or BCOM (if that is a nonempty string),
  42.      or ECOM (if that is a nonempty string),
  43.      or a string _not_ including ECOM_CHAR or space.
  44. */
  45.  
  46. /* maximum expected length of a DTL token */
  47. #define MAXTOKLEN 255
  48. typedef char Token[MAXTOKLEN+1];
  49.  
  50. typedef unsigned char Byte;
  51. typedef char Boolean;
  52.  
  53. #define true  1
  54. #define false 0
  55.  
  56. /* command prefixes */
  57. typedef struct
  58. {
  59.     Byte first_code;
  60.     char * name;
  61.     Boolean has_suffix;
  62.     Byte first_suffix, last_suffix;
  63. } CmdPrefix;
  64.  
  65. CmdPrefix  cmd_prefixes [] =
  66. {
  67.   {0,   SETCHAR, true, 0, 127},
  68.   {128, SET, true, 1, 4},
  69.   {132, SETRULE, false, 0, 0},
  70.   {133, PUT, true, 1, 4},
  71.   {137, PUTRULE, false, 0, 0},
  72.   {138, NOP, false, 0, 0},
  73.   {139, BOP, false, 0, 0},
  74.   {140, EOP, false, 0, 0},
  75.   {141, PUSH, false, 0, 0},
  76.   {142, POP, false, 0, 0},
  77.   {143, RIGHT, true, 1, 4},
  78.   {147, W, true, 0, 4},
  79.   {152, X, true, 0, 4},
  80.   {157, DOWN, true, 1, 4},
  81.   {161, Y, true, 0, 4},
  82.   {166, Z, true, 0, 4},
  83.   {171, FONTNUM, true, 0, 63},
  84.   {235, FONT, true, 1, 4},
  85.   {239, SPECIAL, true, 1, 4},
  86.   {243, FONTDEF, true, 1, 4},
  87.   {247, PRE, false, 0, 0},
  88.   {248, POST, false, 0, 0},
  89.   {249, POSTPOST, false, 0, 0},
  90.   {250, OPCODE, true, 250, 255}
  91. };
  92. /* cmd_prefixes[] */
  93.  
  94. /* table of command names */
  95. typedef char * CmdTable [256];
  96.  
  97. CmdTable cmd_table;
  98.  
  99. /* operation's opcode, name, number of args, string of arguments. */
  100. typedef struct
  101. {
  102.   int code;
  103.   char * name;
  104.   int nargs;
  105.   char * args;
  106. } op_info;
  107.  
  108. /* name of table, first opcode, last opcode, pointer to opcode info. */
  109. typedef struct
  110. {
  111.   char * name;
  112.   int first;
  113.   int last;
  114.   op_info * list;
  115. } op_table;
  116.  
  117. /* Table for opcodes 128 to 170 inclusive. */
  118.  
  119. op_info  op_info_128_170 [] =
  120. {
  121.   {128, SET1, 1, "1"},
  122.   {129, SET2, 1, "2"},
  123.   {130, SET3, 1, "3"},
  124.   {131, SET4, 1, "-4"},
  125.   {132, SETRULE, 2, "-4 -4"},
  126.   {133, PUT1, 1, "1"},
  127.   {134, PUT2, 1, "2"},
  128.   {135, PUT3, 1, "3"},
  129.   {136, PUT4, 1, "-4"},
  130.   {137, PUTRULE, 2, "-4 -4"},
  131.   {138, NOP, 0, ""},
  132.   /* bop:  not counting last argument, a signed address: */
  133.   {139, BOP, 10, "-4 -4 -4 -4 -4 -4 -4 -4 -4 -4"},
  134.   {140, EOP, 0, ""},
  135.   {141, PUSH, 0, ""},
  136.   {142, POP, 0, ""},
  137.   {143, RIGHT1, 1, "-1"},
  138.   {144, RIGHT2, 1, "-2"},
  139.   {145, RIGHT3, 1, "-3"},
  140.   {146, RIGHT4, 1, "-4"},
  141.   {147, W0, 0, ""},
  142.   {148, W1, 1, "-1"},
  143.   {149, W2, 1, "-2"},
  144.   {150, W3, 1, "-3"},
  145.   {151, W4, 1, "-4"},
  146.   {152, X0, 0, ""},
  147.   {153, X1, 1, "-1"},
  148.   {154, X2, 1, "-2"},
  149.   {155, X3, 1, "-3"},
  150.   {156, X4, 1, "-4"},
  151.   {157, DOWN1, 1, "-1"},
  152.   {158, DOWN2, 1, "-2"},
  153.   {159, DOWN3, 1, "-3"},
  154.   {160, DOWN4, 1, "-4"},
  155.   {161, Y0, 0, ""},
  156.   {162, Y1, 1, "-1"},
  157.   {163, Y2, 1, "-2"},
  158.   {164, Y3, 1, "-3"},
  159.   {165, Y4, 1, "-4"},
  160.   {166, Z0, 0, ""},
  161.   {167, Z1, 1, "-1"},
  162.   {168, Z2, 1, "-2"},
  163.   {169, Z3, 1, "-3"},
  164.   {170, Z4, 1, "-4"}
  165. };
  166. /* op_info  op_info_128_170 [] */
  167.  
  168. op_table  op_128_170  =  {"op_128_170", 128, 170, op_info_128_170};
  169.  
  170. /* Table for fnt1 to fnt4 (opcodes 235 to 238) inclusive. */
  171.  
  172. op_info  fnt_n [] =
  173. {
  174.   {235, FONT1, 1, "1"},
  175.   {236, FONT2, 1, "2"},
  176.   {237, FONT3, 1, "3"},
  177.   {238, FONT4, 1, "-4"}
  178. };
  179. /* op_info  fnt_n [] */
  180.  
  181. op_table  fnt  =  {FONT, 235, 238, fnt_n};
  182.  
  183. /* Function prototypes */
  184.  
  185. Void mem_viol __((int sig));
  186. Void give_help (VOID);
  187. int parse __((char * s));
  188. Void process __((char * s));
  189.  
  190. int open_dtl __((char * dtl_file, FILE ** pdtl));
  191. int open_dvi __((char * dvi_file, FILE ** pdvi));
  192.  
  193. int dt2dv __((FILE * dtl, FILE * dvi));
  194.  
  195. Void * gmalloc __((long int size));
  196.  
  197. int cons_cmds __((int nprefixes, CmdPrefix * prefix, CmdTable cmds));
  198.  
  199. size_t getline __((FILE * fp, char * line, int max));
  200. int read_line_char __((FILE * fp, int * c));
  201. int read_char __((FILE * fp, int * ch));
  202.  
  203. COUNT read_variety __((FILE * dtl));
  204. COUNT read_token __((FILE * dtl, char * token));
  205. COUNT skip_space __((FILE * fp, int * ch));
  206. COUNT read_misc __((FILE * fp, Token token));
  207. COUNT read_mes __((FILE * fp, char * token));
  208.  
  209. int unread_char (VOID);
  210.  
  211. int find_command __((char * command, int * opcode));
  212. int xferargs __((FILE * dtl, FILE * dvi, int opcode));
  213.  
  214. int setseq __((FILE * dtl, FILE * dvi));
  215.  
  216. int check_byte __((int byte));
  217. int putbyte __((FILE * dvi, int onebyte));
  218.  
  219. U4 xferhex __((int n,  FILE * dtl,  FILE * dvi));
  220. U4 xferoct __((int n,  FILE * dtl,  FILE * dvi));
  221. U4 xferunsigned __((int n,  FILE * dtl,  FILE * dvi));
  222. S4 xfersigned   __((int n,  FILE * dtl,  FILE * dvi));
  223.  
  224. U4 xferstring __((FILE * dtl, FILE * dvi));
  225. U4 xferlenstring __((int n, FILE * dtl, FILE * dvi));
  226.  
  227. int save_dvi_loc __((int ln));
  228. int restore_dvi_loc __((int ln));
  229.  
  230. int check_bmes __((FILE * dtl));
  231. int check_emes __((FILE * dtl));
  232.  
  233. U4 getunsigned __((FILE * dtl));
  234. S4 getsigned   __((FILE * dtl));
  235.  
  236. int putunsigned __((int n, U4 unum, FILE * dvi));
  237. int putsigned   __((int n, S4 snum, FILE * dvi));
  238.  
  239. S4 xfer_bop_address __((FILE * dtl,  FILE * dvi));
  240. S4 xfer_postamble_address __((FILE * dtl,  FILE * dvi));
  241.  
  242. int puttable __((op_table table, int opcode, FILE * dtl, FILE * dvi));
  243.  
  244. U4 special __((FILE * dtl,  FILE * dvi,  int n));
  245. int fontdef __((FILE * dtl,  FILE * dvi,  int n));
  246.  
  247. U4 preamble __((FILE * dtl,  FILE * dvi));
  248. int postamble __((FILE * dtl,  FILE * dvi));
  249. int post_post __((FILE * dtl,  FILE * dvi));
  250.  
  251. Void dinfo (VOID);
  252. Void dexit __((int n));
  253.  
  254. /* check whether compiler is standard C */
  255. /* at my site, gcc 2.2.2 on Sun/OS uses a BSD library, not an ANSI library */
  256.  
  257. #ifdef __STDC__
  258. # if __STDC__ - 1  /* __STDC__ defined, but != 1 => substandard C */
  259. #  define STD_C (-1)
  260. # else             /* standard C, except for BSD library */
  261. #  define STD_C 1
  262. # endif
  263. #else             /* nonstandard C */
  264. #  define STD_C 0
  265. #endif /* __STDC__ */
  266.  
  267. typedef struct
  268. {
  269.   char * keyword;  /* command line option keyword */
  270.   int * p_var;     /* pointer to option variable */
  271.   char * desc;     /* description of keyword and value */
  272. } Options;
  273.  
  274. Options opts[] =
  275. {
  276.   {"-debug", &debug, "detailed debugging"},
  277.   {"-group", &group, "each DTL command is in parentheses"},
  278.   {NULL, NULL, NULL}
  279. };
  280. /* opts[] */
  281.  
  282. COUNT dtl_line_num = 0;  /* number of DTL file lines read */
  283.  
  284. #define NLOCS  2
  285. long int dvi_loc[NLOCS] = {0L, 0L};  /* fseek offset in DVI file : for strings */
  286.  
  287. char * progname = "";  /* intended for name of this program */
  288. int nfile = 0;  /* number of filename arguments on the command line */
  289.  
  290. #define PRINT_PROGNAME  fprintf (stderr, "%s ", progname)
  291.  
  292. FILE * dtl = stdin;
  293. FILE * dvi = stdout;  /* ! Perilous to monitors! */
  294.  
  295. int
  296. main
  297. #ifdef __STDC__
  298.   (int argc,  char * argv[])
  299. #else
  300.   (argc,  argv)
  301.   int argc;
  302.   char * argv[];
  303. #endif
  304. {
  305.   Void (*handler)(int);  /* Previous signal handler */
  306.  
  307.   progname = argv[0];  /* name of this program */
  308.  
  309.   /* memory violation signal handler */
  310.  
  311.   handler = signal (SIGSEGV, mem_viol);
  312.  
  313.   /* message about compiler */
  314.   /* NB:  Our Sun/OS library is BSD, even though gcc 2.2.2 is ANSI */
  315.  
  316.   fprintf (stderr,
  317.     "program \"%s\" version %s compiled %s %s in %sstandard C.\n",
  318.     progname, VERSION, __DATE__, __TIME__,
  319.     (STD_C == 1 ? "" : (STD_C < 0 ? "sub-" : "non-")));
  320.  
  321.   /* interpret command line arguments */
  322.  
  323.   if (argc < 3)  /* less than two command line arguments, so give help */
  324.     give_help();
  325.   else
  326.   {
  327.     int i;
  328.     for (i=1; i < argc; i++)
  329.       parse (argv[i]);
  330.     if (nfile < 2)  /* less than two filename arguments, so give help */
  331.       give_help();
  332.    else
  333.     /* the real works */
  334.     dt2dv (dtl, dvi);
  335.   }
  336.  
  337.   return 0;  /* OK */
  338. }
  339. /* end main */
  340.  
  341. Void
  342. mem_viol
  343. #ifdef __STDC__
  344.   (int sig)
  345. #else
  346.   (sig)
  347.   int sig;
  348. #endif
  349. {
  350.   Void (* handler) (int);
  351.  
  352.   handler = signal (SIGSEGV, mem_viol);
  353.   if (sig != SIGSEGV)
  354.   {
  355.     PRINT_PROGNAME;
  356.     fprintf (stderr,
  357.       "(mem_viol) : called with wrong signal!\n");
  358.   }
  359.   PRINT_PROGNAME;
  360.   fprintf (stderr, "(mem_viol) : RUNTIME MEMORY ERROR : memory violation, ");
  361.   fprintf (stderr, "dtl line >= ");
  362.   fprintf (stderr, WF, dtl_line_num);
  363.   fprintf (stderr, "\n");
  364.   dexit (1);
  365. }
  366. /* mem_viol */
  367.  
  368. Void
  369. give_help (VOID)
  370. {
  371.   int i;
  372.   char * keyword;
  373.   fprintf (stderr, "usage:   ");
  374.   PRINT_PROGNAME;
  375.   fprintf (stderr, "dtl_file  dvi_file");
  376.   fprintf (stderr, "\n");
  377.   for (i=0; (keyword = opts[i].keyword) != NULL; i++)
  378.   {
  379.     fprintf (stderr, "    ");
  380.     fprintf (stderr, "[%s]", keyword);
  381.     fprintf (stderr, "    ");
  382.     fprintf (stderr, "%s", opts[i].desc);
  383.     fprintf (stderr, "\n");
  384.   }
  385.   fprintf (stderr, "If dtl_file is \"-\", stdin is read.\n");
  386.   fprintf (stderr, "If dvi_file is \"-\", stdout is written.\n");
  387.   fprintf (stderr, "Messages, like this one, go to stderr.\n");
  388. }
  389. /* give_help */
  390.  
  391. int
  392. parse
  393. #ifdef __STDC__
  394.   (char * s)
  395. #else
  396.   (s)
  397.   char * s;
  398. #endif
  399. {
  400.   int i;
  401.   char * keyword;
  402.   for (i=0; (keyword = opts[i].keyword) != NULL; i++)
  403.   {
  404.     if (strncmp (s, keyword, strlen (keyword)) == 0)
  405.     {
  406.       *(opts[i].p_var) = 1;  /* turn option on */
  407.       return i;
  408.     }
  409.   }
  410.   /* not an option, so assume it's a filename */
  411.   process (s);
  412.   return i;
  413. }
  414. /* parse */
  415.  
  416. Void
  417. process
  418. #ifdef __STDC__
  419.   (char * s)
  420. #else
  421.   (s)
  422.   char * s;
  423. #endif
  424. {
  425.   extern FILE * dtl, * dvi;
  426.   extern int nfile;
  427.   if (nfile == 0)  /* first filename assumed to be DTL input */
  428.   {
  429.     if (strcmp (s, "-") == 0)
  430.       dtl = stdin;
  431.     else
  432.       open_dtl (s, &dtl);
  433.   }
  434.   else if (nfile == 1)  /* second filename assumed to be DVI output */
  435.   {
  436.     if (strcmp (s, "-") == 0)
  437.       dvi = stdout;
  438.     else
  439.       open_dvi (s, &dvi);
  440.   }
  441.   else
  442.   {
  443.     PRINT_PROGNAME;
  444.     fprintf (stderr,
  445.       "(process) : at most two filenames allowed.\n");
  446.     exit (1);
  447.   }
  448.   ++ nfile;
  449. }
  450. /* process */
  451.  
  452. int
  453. open_dtl
  454. #ifdef __STDC__
  455.   (char * dtl_file, FILE ** pdtl)
  456. #else
  457.   (dtl_file, pdtl)
  458.   char * dtl_file;
  459.   FILE ** pdtl;
  460. #endif
  461. /* I:  dtl_file;  I:  pdtl;  O:  *pdtl. */
  462. {
  463.   if (pdtl == NULL)
  464.   {
  465.     PRINT_PROGNAME;
  466.     fprintf (stderr,
  467.       "(open_dtl) : INTERNAL ERROR : address of dtl variable is NULL.\n");
  468.     dexit (1);
  469.   }
  470.  
  471.   *pdtl = fopen (dtl_file, "r");
  472.  
  473.   if (*pdtl == NULL)
  474.   {
  475.     PRINT_PROGNAME;
  476.     fprintf (stderr,
  477.       "(open_dtl) : DTL FILE ERROR : Cannot open \"%s\" for text reading.\n",
  478.       dtl_file);
  479.     dexit (1);
  480.   }
  481.  
  482.   return 1;  /* OK */
  483. }
  484. /* open_dtl */
  485.  
  486. int
  487. open_dvi
  488. #ifdef __STDC__
  489.   (char * dvi_file, FILE ** pdvi)
  490. #else
  491.   (dvi_file, pdvi)
  492.   char * dvi_file;
  493.   FILE ** pdvi;
  494. #endif
  495. /* I:  dvi_file;  I:  pdvi;  O:  *pdvi. */
  496. {
  497.   if (pdvi == NULL)
  498.   {
  499.     PRINT_PROGNAME;
  500.     fprintf (stderr,
  501.     "(open_dvi) : INTERNAL ERROR : address of dvi variable is NULL.\n");
  502.     dexit (1);
  503.   }
  504.  
  505.   *pdvi = fopen (dvi_file, "wb");
  506.  
  507.   if (*pdvi == NULL)
  508.   {
  509.     PRINT_PROGNAME;
  510.     fprintf (stderr,
  511.       "(open_dvi) : DVI FILE ERROR : Cannot open \"%s\" for binary writing.\n",
  512.       dvi_file);
  513.     dexit (1);
  514.   }
  515.  
  516.   return 1;  /* OK */
  517. }
  518. /* open_dvi */
  519.  
  520. COUNT dtl_read = 0;  /* bytes read from dtl file */
  521. COUNT dvi_written = 0;  /* bytes written to dvi file */
  522. word_t last_bop_address = -1;  /* byte address of last bop; first bop uses -1 */
  523. word_t postamble_address = -1;  /* byte address of postamble */
  524. COUNT ncom = 0;  /* commands successfully read and interpreted from dtl file */
  525. COUNT com_read = 0;  /* bytes read in current (command and arguments), */
  526.                       /* since and including the opening BCOM_CHAR, if any */
  527.  
  528. int
  529. dt2dv
  530. #ifdef __STDC__
  531.   (FILE * dtl, FILE * dvi)
  532. #else
  533.   (dtl, dvi)
  534.   FILE * dtl;
  535.   FILE * dvi;
  536. #endif
  537. {
  538.   int nprefixes = 0;  /* number of prefixes in cmd_prefixes[] list. */
  539.   Token dtl_cmd = "";  /* DTL command name */
  540.   COUNT nread = 0;  /* number of bytes read by a function from dtl file. */
  541.  
  542.   nprefixes = sizeof (cmd_prefixes) / sizeof (CmdPrefix);
  543.  
  544.   /* Construct array of all 256 DTL commands */
  545.  
  546.   (Void) cons_cmds (nprefixes, cmd_prefixes, cmd_table);
  547.  
  548.   /* DTL commands have the form "[ ]*command arg ... arg[ ]*", */
  549.   /* possibly enclosed in a BCOM, ECOM pair, */
  550.   /* and are separated by optional whitespace, typically newlines. */
  551.   /* That is, each command and its arguments are parenthesised, */
  552.   /* with optional spaces after the BCOM and before the ECOM, if any. */
  553.  
  554.   /* dt2dv is now at the very start of the DTL file */
  555.  
  556.   dtl_line_num = 0;
  557.   dtl_read = 0;
  558.  
  559.   /* The very first thing should be the "variety" signature */
  560.  
  561.   nread = read_variety (dtl);
  562.  
  563.   /* while not end of dtl file or reading error, */
  564.   /*   read, interpret, and write commands */
  565.  
  566.   while (!feof (dtl))
  567.   {
  568.     int opcode;
  569.  
  570.     com_read = 0;
  571.  
  572.     if (group)
  573.     {
  574.       /* BCOM check */
  575.       Token token = "";  /* DTL token */
  576.       nread = read_token (dtl, token);
  577.       /* test for end of input, or reading error */
  578.       if (strlen (token) == 0)
  579.       {
  580.     if (debug)
  581.     {
  582.           PRINT_PROGNAME;
  583.       fprintf (stderr, "(dt2dv) : end of input, or reading error.\n");
  584.     }
  585.     break;
  586.       }
  587.       /* test whether this command begins correctly */
  588.       else if (strcmp (token, BCOM) != 0)
  589.       {
  590.         PRINT_PROGNAME;
  591.     fprintf (stderr, "(dt2dv) : DTL FILE ERROR : ");
  592.         fprintf (stderr, "command must begin with \"%s\", ", BCOM);
  593.         fprintf (stderr, "not '%c' (%d).\n", token[0], token[0]);
  594.     dexit (1);
  595.       }
  596.       /* end BCOM check */
  597.     }
  598.  
  599.     /* read the command name */
  600.     nread = read_token (dtl, dtl_cmd);
  601.     /* test for end of input, or reading error */
  602.     if (strlen (dtl_cmd) == 0)
  603.     {
  604.       if (debug)
  605.       {
  606.         PRINT_PROGNAME;
  607.     fprintf (stderr,
  608.       "(dt2dv) : end of input, or reading error.\n");
  609.       }
  610.       break;
  611.     }
  612.     else
  613.     {
  614.       if (debug)
  615.       {
  616.         PRINT_PROGNAME;
  617.     fprintf (stderr, "(dt2dv) : command ");
  618.         fprintf (stderr, WF, ncom);
  619.         fprintf (stderr, " = \"%s\".\n", dtl_cmd);
  620.       }
  621.  
  622.       /* find opcode for this command */
  623.       if (find_command (dtl_cmd, &opcode) == 1)
  624.       {
  625.     /* write the opcode, if we can */
  626.     putbyte (dvi, opcode);
  627.  
  628.     /* treat the arguments, if any */
  629.     xferargs (dtl, dvi, opcode);
  630.       }
  631.       else if (dtl_cmd[0] == BSEQ_CHAR)
  632.       {
  633.     /* sequence of font characters for SETCHAR */
  634.     setseq (dtl, dvi);
  635.       }
  636.       else
  637.       {
  638.         PRINT_PROGNAME;
  639.     fprintf (stderr,
  640.       "(dt2dv) : DTL FILE ERROR : unknown command \"%s\".\n",
  641.       dtl_cmd);
  642.     dexit (1);
  643.       }
  644.     }
  645.  
  646.     if (group)
  647.     {
  648.       /* seek ECOM after command's last argument and optional whitespace */
  649.       Token token = "";  /* DTL token */
  650.       nread = read_token (dtl, token);
  651.       /* test for end of input, or reading error */
  652.       if (strlen (token) == 0)
  653.       {
  654.     if (debug)
  655.     {
  656.           PRINT_PROGNAME;
  657.       fprintf (stderr,
  658.         "(dt2dv) : end of input, or reading error.\n");
  659.     }
  660.     break;
  661.       }
  662.       if (strcmp (token, ECOM) != 0)
  663.       {
  664.         PRINT_PROGNAME;
  665.     fprintf (stderr, "(dt2dv) : DTL FILE ERROR : ");
  666.         fprintf (stderr, "\"%s\" expected, not '%c' (%d).\n",
  667.       ECOM, token[0], token[0]);
  668.     dexit (1);
  669.       }
  670.       /* end ECOM check */
  671.     }
  672.  
  673.     ++ ncom;  /* one more command successfully read and interpreted */
  674.   }
  675.   /* end while */
  676.  
  677.   PRINT_PROGNAME;
  678.   fprintf (stderr, "(dt2dv) : Read ");
  679.   fprintf (stderr, WF, dtl_read);
  680.   fprintf (stderr, " DTL bytes, wrote ");
  681.   fprintf (stderr, WF, dvi_written);
  682.   fprintf (stderr, " DVI bytes.\n");
  683.   fprintf (stderr, "Completely interpreted ");
  684.   fprintf (stderr, WF, ncom);
  685.   fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
  686.  
  687.   return 1;  /* OK */
  688. }
  689. /* dt2dv */
  690.  
  691. Void *
  692. gmalloc
  693. #ifdef __STDC__
  694.   (long int size)
  695. #else
  696.   (size)
  697.   long int size;
  698. #endif
  699. {
  700.   Void * p = NULL;
  701.   if (size < 1)
  702.   {
  703.     PRINT_PROGNAME;
  704.     fprintf (stderr, "(gmalloc) : INTERNAL ERROR : ");
  705.     fprintf (stderr,
  706.       "unreasonable request to malloc %ld bytes\n",
  707.       size);
  708.     dexit (1);
  709.   }
  710.   p = malloc ((size_t) size);
  711.   if (p == NULL)
  712.   {
  713.     PRINT_PROGNAME;
  714.     fprintf (stderr, "(gmalloc) : MEMORY ALLOCATION ERROR : ");
  715.     fprintf (stderr,
  716.       "operating system failed to malloc %ld bytes\n",
  717.       size);
  718.     dexit (1);
  719.   }
  720.   return (p);
  721. }
  722. /* gmalloc */
  723.  
  724. int
  725. cons_cmds
  726. #ifdef __STDC__
  727.   (int nprefixes, CmdPrefix * prefix, CmdTable cmds)
  728. #else
  729.   (nprefixes, prefix, cmds)
  730.   int nprefixes;
  731.   CmdPrefix * prefix;
  732.   CmdTable cmds;
  733. #endif
  734. {
  735.   int code;  /* first opcode for a given command prefix */
  736.   int opcode;  /* command's opcode */
  737.   int nsuffixes;  /* number of commands with a given prefix */
  738.   int isuffix;  /**** integer suffix, of at most three digits ****/
  739.   String suffix;  /* suffix string generated from integer suffix */
  740.   size_t plen = 0;  /* prefix length */
  741.   size_t slen;  /* suffix length */
  742.   size_t clen;  /* whole command name length */
  743.   int i, j;  /* loop indices */
  744.  
  745.   for (i=0; i < nprefixes; prefix++, i++)
  746.   {
  747.     code = prefix->first_code;
  748.     if (code < 0 || code > 255)
  749.     {
  750.       PRINT_PROGNAME;
  751.       fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
  752.       fprintf (stderr,
  753.         "prefix listed internally with code = %d, must be 0 to 255\n",
  754.         code);
  755.       dexit (1);
  756.     }
  757.     if (prefix->has_suffix)
  758.     {
  759.       plen = strlen (prefix->name);
  760.       /**** Suffixes in DTL are Integers, in Sequence */
  761.       if (prefix->last_suffix < prefix->first_suffix)
  762.       {
  763.         PRINT_PROGNAME;
  764.         fprintf (stderr, "(cons_cmds) : INTERNAL ERROR : ");
  765.         fprintf (stderr,
  766.           "prefix's last suffix %d < first suffix (%d)\n",
  767.           prefix->last_suffix, prefix->first_suffix);
  768.         dexit (1);
  769.       }
  770.       nsuffixes = prefix->last_suffix - prefix->first_suffix + 1;
  771.       opcode = prefix->first_code;
  772.       for (j=0; j < nsuffixes; j++, opcode++)
  773.       {
  774.         isuffix = prefix->first_suffix + j;
  775.         if (0 <= code && code <= 127)  /* SETCHAR */
  776.         {
  777.           /* SETCHAR's suffix is written in uppercase hexadecimal */
  778.           sprintf (suffix, "%02X", isuffix);
  779.         }
  780.         else  /* 128 <= code && code <= 255 */  /* other DTL commands */
  781.         {
  782.           /* other commands' suffices are written in decimal */
  783.           sprintf (suffix, "%d", isuffix);
  784.         }
  785.         slen = strlen (suffix);
  786.         clen = plen + slen;
  787.         cmds[opcode] = gmalloc (clen+1);
  788.         strcpy (cmds[opcode], prefix->name);
  789.         strcat (cmds[opcode], suffix);
  790.       }
  791.     }
  792.     else /* command name = prefix */
  793.     {
  794.       clen = plen;
  795.       opcode = prefix->first_code;
  796.       cmds[opcode] = gmalloc (clen+1);
  797.       strcpy (cmds[opcode], prefix->name);
  798.     }
  799.   }
  800.  
  801.   return 1;  /* OK */
  802. }
  803. /* cons_cmds */
  804.  
  805. COUNT
  806. read_variety
  807. #ifdef __STDC__
  808.   (FILE * dtl)
  809. #else
  810.   (dtl)
  811.   FILE * dtl;
  812. #endif
  813. /* read and check DTL variety signature */
  814. /* return number of DTL bytes written */
  815. /* DTL variety is _NEVER_ grouped by BCOM and ECOM. */
  816. /* Uniformity here enables the program easily to modify its behavior. */
  817. {
  818.   COUNT vread = 0;  /* number of DTL bytes read by read_variety */
  819.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  820.   Token token = "";
  821.  
  822.   /* read the DTL VARIETY keyword */
  823.   nread =
  824.   read_token (dtl, token);
  825.   vread += nread;
  826.   /* test whether signature begins correctly */
  827.   if (strcmp (token, "variety") != 0)
  828.   {
  829.     PRINT_PROGNAME;
  830.     fprintf (stderr, "(read_variety) : DTL FILE ERROR : ");
  831.     fprintf (stderr, "DTL signature must begin with \"%s\", not \"%s\".\n",
  832.       "variety", token);
  833.     dexit (1);
  834.   }
  835.  
  836.   /* read the DTL variety */
  837.   nread =
  838.   read_token (dtl, token);
  839.   vread += nread;
  840.   /* test whether variety is correct */
  841.   if (strcmp (token, VARIETY) != 0)
  842.   {
  843.     PRINT_PROGNAME;
  844.     fprintf (stderr, "(read_variety) : DTL FILE ERROR : ");
  845.     fprintf (stderr, "DTL variety must be \"%s\", not \"%s\".\n",
  846.       VARIETY, token);
  847.     dexit (1);
  848.   }
  849.  
  850.   PRINT_PROGNAME;
  851.   fprintf (stderr, "(read_variety) : DTL variety %s is OK.\n", VARIETY);
  852.  
  853.   return vread;  /* OK */
  854. }
  855. /* read_variety */
  856.  
  857. COUNT
  858. read_token
  859. #ifdef __STDC__
  860.   (FILE * dtl, char * token)
  861. #else
  862.   (dtl, token)
  863.   FILE * dtl;
  864.   char * token;
  865. #endif
  866. /* read next token from dtl file. */
  867. /* return number of DTL bytes read. */
  868. /* A token is:
  869.      a string from BMES_CHAR to the next unescaped EMES_CHAR, inclusive;
  870.      BCOM or ECOM, unless these are empty strings;
  871.      BSEQ or ESEQ;
  872.      any other sequence of non-whitespace characters.
  873. */
  874. {
  875.   COUNT nread;  /* number of DTL bytes read by read_token */
  876.   int ch;  /* most recent character read */
  877.  
  878.   nread = 0;
  879.  
  880.   /* obtain first non-space character */
  881.   /* add to nread the number of characters read from dtl by skip_space */
  882.   nread +=
  883.   skip_space (dtl, &ch);
  884.  
  885.   if (ch < 0)
  886.   {
  887.     /* end of dtl file */
  888.     /* write an empty token */
  889.     strcpy (token, "");
  890.     if (debug)
  891.     {
  892.       PRINT_PROGNAME;
  893.       fprintf (stderr, "(read_token) : end of dtl file.\n");
  894.     }
  895.   }
  896.   else if (group && ch == BCOM_CHAR)
  897.   {
  898.     strcpy (token, BCOM);
  899.   }
  900.   else if (group && ch == ECOM_CHAR)
  901.   {
  902.     strcpy (token, ECOM);
  903.   }
  904.   else
  905.   {
  906.     token[0] = ch;
  907.     token[1] = '\0';
  908.     if (ch == BMES_CHAR)  /* string token; read until unescaped EMES_CHAR */
  909.     {
  910.       nread +=
  911.       read_mes (dtl, token+1);
  912.     }
  913.     else if (ch == BSEQ_CHAR || ch == ESEQ_CHAR)
  914.     {
  915.       /* token is complete */
  916.     }
  917.     else  /* any other string not containing (ECOM_CHAR or) whitespace */
  918.     {
  919.       nread +=
  920.       read_misc (dtl, token+1);
  921.     }
  922.   }
  923.  
  924.   if (debug)
  925.   {
  926.     PRINT_PROGNAME;
  927.     fprintf (stderr,
  928.       "(read_token) : token = \"%s\"\n",
  929.       token);
  930.   }
  931.  
  932.   return (nread);  /* number of bytes read from dtl file */
  933. }
  934. /* read_token */
  935.  
  936. size_t
  937. getline
  938. #ifdef __STDC__
  939.   (FILE * fp, char * line, int max)
  940. #else
  941.   (fp, line, max)
  942.   FILE * fp;
  943.   char * line;
  944.   int max;
  945. #endif
  946. /* read a line from fp, return length */
  947. /* adapted from K&R (second, alias ANSI C, edition, 1988), page 165 */
  948. {
  949.   if (fgets (line, max, fp) == NULL)
  950.     return 0;
  951.   else
  952.     return strlen (line);
  953. }
  954. /* getline */
  955.  
  956. int
  957. read_line_char
  958. #ifdef __STDC__
  959.   (FILE * fp, int * c)
  960. #else
  961.   (fp, c)
  962.   FILE * fp;
  963.   int * c;
  964. #endif
  965. /* read one character from dtl_line if possible, */
  966. /* otherwise read another dtl_line from fp */
  967. /* return 1 if a character is read, 0 if at end of fp file */
  968. {
  969.   extern Line dtl_line;
  970.   if (dtl_line.len == 0 || dtl_line.next >= dtl_line.len)
  971.   {
  972.     /* refill line buffer */
  973.     dtl_line.len = getline (fp, dtl_line.buf, MAXLINE);
  974.     dtl_line.next = 0;
  975.     if (debug)
  976.     {
  977.       PRINT_PROGNAME;
  978.       fprintf (stderr, "(read_line_char) : new DTL input line:\n");
  979.       fprintf (stderr, "\"%s\"", dtl_line.buf);
  980.       fprintf (stderr, "\n");
  981.     }
  982.     if (dtl_line.len == 0)
  983.     {
  984.       /* at end of DTL file */
  985.       if (debug)
  986.       {
  987.         PRINT_PROGNAME;
  988.         fprintf (stderr, "(read_line_char) : end of DTL file\n");
  989.         dinfo();
  990.       }
  991.       return 0;
  992.     }
  993.   }
  994.   *c = dtl_line.buf [dtl_line.next ++];
  995.   ++ dtl_read;
  996.   ++ com_read;  /* count another DTL command character */
  997.   return 1;
  998. }
  999. /* read_line_char */
  1000.  
  1001. int
  1002. read_char
  1003. #ifdef __STDC__
  1004.   (FILE * fp, int * ch)
  1005. #else
  1006.   (fp, ch)
  1007.   FILE * fp;
  1008.   int * ch;
  1009. #endif
  1010. /* Read next character, if any, from file fp. */
  1011. /* Write it into *ch. */
  1012. /* If no character is read, then *ch value < 0. */
  1013. /* Return 1 if OK, 0 if EOF or error. */
  1014. {
  1015.   int status = 1;
  1016.   int c;  /* in case ch points awry, we still have something in c. */
  1017.   if (read_line_char (fp, &c) == 0)
  1018.   {
  1019.     /* end of fp file, or error reading it */
  1020.     status = 0;
  1021.   }
  1022.   else
  1023.   {
  1024.     if (c > 255)
  1025.     {
  1026.       PRINT_PROGNAME;
  1027.       fprintf (stderr,
  1028.         "(read_char) : character %d not in range 0 to 255\n",
  1029.         c);
  1030.       dinfo();
  1031.       status = 0;
  1032.     }
  1033.     else if ( ! isprint (c) && ! isspace (c))
  1034.     {
  1035.       PRINT_PROGNAME;
  1036.       fprintf (stderr,
  1037.         "(read_char) : character %d %s.\n",
  1038.         c,
  1039.         "not printable and not white space");
  1040.       dinfo();
  1041.       status = 0;
  1042.     }
  1043.   }
  1044.   *ch = c;
  1045.   return status;
  1046. }
  1047. /* read_char */
  1048.  
  1049. COUNT
  1050. skip_space
  1051. #ifdef __STDC__
  1052.   (FILE * fp, int * ch)
  1053. #else
  1054.   (fp, ch)
  1055.   FILE * fp;
  1056.   int * ch;
  1057. #endif
  1058. /* Skip whitespace characters in file fp. */
  1059. /* Write in *ch the last character read from fp, */
  1060. /*   or < 0 if fp could not be read. */
  1061. /* Return number of characters read from fp. */
  1062. {
  1063.   int c;  /* character read (if any) */
  1064.   COUNT count;  /* number (0 or more) of whitespace characters read */
  1065.   int nchar;  /* number (0 or 1) of characters read by read_char */
  1066.  /* loop ends at:  end of fp file, or reading error, or not a white space */
  1067.   for (count=0;  ((nchar = read_char (fp, &c)) == 1 && isspace (c));  ++count)
  1068.   {
  1069.     /* otherwise, more white spaces to skip */
  1070.     if (debug)
  1071.     {
  1072.       /* report when each DTL end of line is reached */
  1073.       if (c == '\n')
  1074.       {
  1075.         PRINT_PROGNAME;
  1076.         fprintf (stderr, "(skip_space) : ");
  1077.         fprintf (stderr, "end of DTL line (at least) ");
  1078.         fprintf (stderr, WF, dtl_line_num);
  1079.         fprintf (stderr, "\n");
  1080.         ++ dtl_line_num;
  1081.       }
  1082.     }
  1083.   }
  1084.   if (nchar == 0)
  1085.   {
  1086.     c = -1;
  1087.   }
  1088.   *ch = c;  /* c will be < 0 if read_char could not read fp */
  1089.   return (count + nchar);
  1090. }
  1091. /* skip_space */
  1092.  
  1093. COUNT
  1094. read_misc
  1095. #ifdef __STDC__
  1096.   (FILE * fp, Token token)
  1097. #else
  1098.   (fp, token)
  1099.   FILE * fp;
  1100.   Token token;
  1101. #endif
  1102. {
  1103.   int c;
  1104.   int count;
  1105.  /* loop ends at:  end of fp file, or reading error, or a space */
  1106.   for (count=0;  count <= MAXTOKLEN;  ++count)
  1107.   {
  1108.     if (read_char (fp, &c) == 0  ||  isspace (c))
  1109.       break;
  1110.     if (group && c == ECOM_CHAR)
  1111.     {
  1112.       (Void) unread_char ();
  1113.       break;
  1114.     }
  1115.  
  1116.     token[count] = c;
  1117.   }
  1118.   token[count] = '\0';
  1119.   return count;
  1120. }
  1121. /* read_misc */
  1122.  
  1123. COUNT
  1124. read_mes
  1125. #ifdef __STDC__
  1126.   (FILE * fp, char * token)
  1127. #else
  1128.   (fp, token)
  1129.   FILE * fp;
  1130.   char * token;
  1131. #endif
  1132. /* called **AFTER** a BMES_CHAR has been read */
  1133. /* read file fp for characters up to next unescaped EMES_CHAR */
  1134. /* this is called a "string token" */
  1135. /* write string, including EMES_CHAR, into token[] */
  1136. /* return number of characters read from fp */
  1137. {
  1138.   COUNT dtl_count;  /* number of DTL characters read by read_mes from fp */
  1139.   int more;  /* flag more == 0 to terminate loop */
  1140.   int escape;  /* flag escape == 1 if previous character was ESC_CHAR */
  1141.   int ch;  /* current DTL character */
  1142.   escape = 0;
  1143.   more = 1;
  1144.   dtl_count = 0;
  1145.   while (more)
  1146.   {
  1147.     if (read_char (fp, &ch) == 0)
  1148.     {
  1149.       /* end of fp file, or reading error */
  1150.       more = 0;
  1151.     }
  1152.     else  /* error checking passed */
  1153.     {
  1154.       ++ dtl_count;
  1155.       if (ch == EMES_CHAR && escape == 0)  /* end of string */
  1156.       {
  1157.         /* include final EMES_CHAR */
  1158.         * token ++ = ch;
  1159.         more = 0;
  1160.       }
  1161.       else if (ch == ESC_CHAR && escape == 0)
  1162.       {
  1163.         /* next character is not end of string */
  1164.         escape = 1;
  1165.       }
  1166.       else
  1167.       {
  1168.         /* store any other character, */
  1169.         /* including escaped EMES_CHAR and ESC_CHAR*/
  1170.         * token ++ = ch;
  1171.         escape = 0;
  1172.       }
  1173.     }
  1174.   }
  1175.   * token = '\0';
  1176.   return dtl_count;
  1177. }
  1178. /* read_mes */
  1179.  
  1180. int
  1181. unread_char (VOID)
  1182. /* wind input back, to allow rereading of one character */
  1183. /* return 1 if this works, 0 on error */
  1184. {
  1185.   extern Line dtl_line;
  1186.   int status;
  1187.   if (dtl_line.next > 0)
  1188.   {
  1189.     -- dtl_line.next;  /* back up one character in dtl_line */
  1190.     -- dtl_read;  /* correct the count of DTL characters */
  1191.     -- com_read;  /* count another DTL command character */
  1192.     status = 1;  /* OK */
  1193.   }
  1194.   else /* current DTL line is empty */
  1195.   {
  1196.     status = 0;  /* error */
  1197.   }
  1198.   return status;
  1199. }
  1200. /* unread_char */
  1201.  
  1202. int
  1203. find_command
  1204. #ifdef __STDC__
  1205.   (char * command, int * opcode)
  1206. #else
  1207.   (command, opcode)
  1208.   char * command;
  1209.   int * opcode;
  1210. #endif
  1211. {
  1212.   int found;
  1213.   int i;
  1214.  
  1215.   found = 0;
  1216.   for (i=0; i < 256; i++)
  1217.   {
  1218.     if (strcmp (command, cmd_table[i]) == 0)
  1219.     {
  1220.       found = 1;
  1221.       break;
  1222.     }
  1223.   }
  1224.  
  1225.   *opcode = i;
  1226.  
  1227.   return found;
  1228. }
  1229. /* find_command */
  1230.  
  1231. int
  1232. check_byte
  1233. #ifdef __STDC__
  1234.   (int byte)
  1235. #else
  1236.   (byte)
  1237.   int byte;
  1238. #endif
  1239. {
  1240.   if (byte < 0 || byte > 255)
  1241.   {
  1242.     PRINT_PROGNAME;
  1243.     fprintf (stderr, "(check_byte) : INTERNAL ERROR : ");
  1244.     fprintf (stderr, "byte %d not in the range of 0 to 255.\n", byte);
  1245.     dexit (1);
  1246.   }
  1247.   return 1;  /* OK */
  1248. }
  1249. /* check_byte */
  1250.  
  1251. int
  1252. xferargs
  1253. #ifdef __STDC__
  1254.   (FILE * dtl, FILE * dvi, int opcode)
  1255. #else
  1256.   (dtl, dvi, opcode)
  1257.   FILE * dtl;
  1258.   FILE * dvi;
  1259.   int opcode;
  1260. #endif
  1261. {
  1262.   int n;
  1263.  
  1264.   if (opcode >= 0 && opcode <= 127)
  1265.     ;  /* SETCHAR uses no data */
  1266.   else if (opcode >= 128 && opcode <= 170)
  1267.   {
  1268.     word_t this_bop_address = last_bop_address;
  1269.  
  1270.     if (opcode == 139)  /* BOP */
  1271.     {
  1272.       this_bop_address = dvi_written - 1;
  1273.     }
  1274.     puttable (op_128_170, opcode, dtl, dvi);
  1275.     if (opcode == 139)  /* BOP */
  1276.     {
  1277.       xfer_bop_address (dtl, dvi);
  1278.       last_bop_address = this_bop_address;
  1279.     }
  1280.   }
  1281.   else if (opcode >= 171 && opcode <= 234)
  1282.     ;  /* FONTNUM uses no data */
  1283.   else if (opcode >= 235 && opcode <= 238)
  1284.     puttable (fnt, opcode, dtl, dvi);
  1285.   else if (opcode >= 239 && opcode <= 242)
  1286.   {
  1287.     n = opcode - 238;
  1288.     special (dtl, dvi, n);
  1289.   }
  1290.   else if (opcode >= 243 && opcode <= 246)
  1291.   {
  1292.     n = opcode - 242;
  1293.     fontdef (dtl, dvi, n);
  1294.   }
  1295.   else if (opcode == 247)
  1296.     preamble (dtl, dvi);
  1297.   else if (opcode == 248)
  1298.     postamble (dtl, dvi);
  1299.   else if (opcode == 249)
  1300.     post_post (dtl, dvi);
  1301.   else if (opcode >= 250 && opcode <= 255)
  1302.     ;  /* these, undefined, opcodes use no data */
  1303.   else
  1304.   {
  1305.     PRINT_PROGNAME;
  1306.     fprintf (stderr,
  1307.       "(xferargs) : opcode %d not handled.\n",
  1308.       opcode);
  1309.   }
  1310.  
  1311.   return 1;  /* OK */
  1312. }
  1313. /* xferargs */
  1314.  
  1315. int
  1316. setseq
  1317. #ifdef __STDC__
  1318.   (FILE * dtl, FILE * dvi)
  1319. #else
  1320.   (dtl, dvi)
  1321.   FILE * dtl;
  1322.   FILE * dvi;
  1323. #endif
  1324. /* Called _after_ a BSEQ_CHAR command */
  1325. /* Read bytes from dtl file, */
  1326. /* writing corresponding SETCHAR or SET1 commands to DVI file, */
  1327. /* _until_ unescaped ESEQ_CHAR is found */
  1328. /* Return 1 if OK, 0 on error */
  1329. /****  dt2dv assumes 8 bit characters,      ****/
  1330. /****  but some day one might change that.  ****/
  1331. {
  1332.   int status = 1;  /* status = 1 if OK, 0 if error */
  1333.   int more;  /* sequence of font characters continuing? */
  1334.   int escape = 0;  /* flag set if previous character was an escape */
  1335.   int ch;  /* character read from DTL file */
  1336.   more = 1;
  1337.   while (more)
  1338.   {
  1339.     /* ignore read_char status, to allow unprintable characters */
  1340.     (Void) read_char (dtl, &ch);
  1341.     /* but check for end of dtl file, or serious file reading error */
  1342.     if (ch < 0)
  1343.     {
  1344.       PRINT_PROGNAME;
  1345.       fprintf (stderr, "(setseq) : ");
  1346.       fprintf (stderr, "end of dtl file, ");
  1347.       fprintf (stderr, "or serious dtl file reading error\n");
  1348.       dinfo();
  1349.       more = 0;
  1350.       status = 0;  /* bad news */
  1351.     }
  1352.     else  /* read dtl file, okay */
  1353.     {
  1354.       if (ch == ESC_CHAR && escape == 0)  /* escape next character */
  1355.       {
  1356.         escape = 1;
  1357.       }
  1358.       else
  1359.       {
  1360.         if (ch == ESEQ_CHAR && escape == 0)  /* end of sequence */
  1361.         {
  1362.           more = 0;
  1363.         }
  1364.         else if (ch <= 127)  /* can use SETCHAR */
  1365.         {
  1366.           putbyte (dvi, ch);
  1367.         }
  1368.         else if (ch <= 255)  /* can use SET1 */
  1369.         {
  1370.           putbyte (dvi, 128);  /* SET1 opcode */
  1371.           putunsigned (1, (U4) ch, dvi);
  1372.         }
  1373.         else
  1374.         {
  1375.           PRINT_PROGNAME;
  1376.           fprintf (stderr, "(setseq) : ");
  1377.           fprintf (stderr,
  1378.             "ERROR : DTL character %d is not in range 0 to 255\n",
  1379.             ch);
  1380.           dexit (1);
  1381.           more = 0;
  1382.           status = 0;  /* Error, because dt2dv assumes 8 bit characters */
  1383.         }
  1384.         escape = 0;  /* current ch is not an escape character */
  1385.       }
  1386.     }
  1387.   }
  1388.   return status;
  1389. }
  1390. /* setseq */
  1391.  
  1392. int
  1393. putbyte
  1394. #ifdef __STDC__
  1395.   (FILE * dvi, int byte)
  1396. #else
  1397.   (dvi, byte)
  1398.   FILE * dvi;
  1399.   int byte;
  1400. #endif
  1401. {
  1402.   check_byte (byte);
  1403. /*  if (fprintf (dvi, "%c", byte) != 1) */
  1404.   if (fprintf (dvi, "%c", byte) < 0)
  1405.   {
  1406.     PRINT_PROGNAME;
  1407.     fprintf (stderr,
  1408.       "(putbyte) : DVI FILE ERROR : cannot write to dvi file.\n");
  1409.     dexit (1);
  1410.   }
  1411.   ++ dvi_written;
  1412.   return 1;  /* OK */
  1413. }
  1414. /* putbyte */
  1415.  
  1416. U4
  1417. xferhex
  1418. #ifdef __STDC__
  1419.   (int n, FILE * dtl, FILE * dvi)
  1420. #else
  1421.   (n, dtl, dvi)
  1422.   int n;
  1423.   FILE * dtl;
  1424.   FILE * dvi;
  1425. #endif
  1426. /* translate unsigned n-byte hexadecimal number from dtl to dvi file. */
  1427. /* return value of hexadecimal number */
  1428. {
  1429.   U4 unum = 0;  /* at most this space needed */
  1430.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  1431.   int nconv = 0;  /* number of arguments converted by sscanf */
  1432.   Token token = "";  /* DTL token */
  1433.  
  1434.   if (n < 1 || n > 4)
  1435.   {
  1436.     PRINT_PROGNAME;
  1437.     fprintf (stderr,
  1438.       "(xferhex) : INTERNAL ERROR : asked for %d bytes.  Must be 1 to 4.\n",
  1439.       n);
  1440.     dexit (1);
  1441.   }
  1442.  
  1443.   nread =
  1444.   read_token (dtl, token);
  1445.  
  1446.   nconv = sscanf (token, XF4, &unum);
  1447.  
  1448.   if (nconv < 1)
  1449.   {
  1450.     PRINT_PROGNAME;
  1451.     fprintf (stderr, "(xferhex) : DTL FILE ERROR :  %s \"%s\".\n",
  1452.       "hexadecimal number expected, not", token);
  1453.     dexit (1);
  1454.   }
  1455.  
  1456.   putunsigned (n, unum, dvi);
  1457.  
  1458.   return unum;
  1459. }
  1460. /* xferhex */
  1461.  
  1462. U4
  1463. xferoct
  1464. #ifdef __STDC__
  1465.   (int n, FILE * dtl, FILE * dvi)
  1466. #else
  1467.   (n, dtl, dvi)
  1468.   int n;
  1469.   FILE * dtl;
  1470.   FILE * dvi;
  1471. #endif
  1472. /* translate unsigned n-byte octal number from dtl to dvi file. */
  1473. /* return value of octal number */
  1474. {
  1475.   U4 unum = 0;  /* at most this space needed */
  1476.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  1477.   int nconv = 0;  /* number of arguments converted by sscanf */
  1478.   Token token = "";  /* DTL token */
  1479.  
  1480.   if (n < 1 || n > 4)
  1481.   {
  1482.     PRINT_PROGNAME;
  1483.     fprintf (stderr,
  1484.       "(xferoct) : INTERNAL ERROR : asked for %d bytes.  Must be 1 to 4.\n",
  1485.       n);
  1486.     dexit (1);
  1487.   }
  1488.  
  1489.   nread =
  1490.   read_token (dtl, token);
  1491.  
  1492.   nconv = sscanf (token, OF4, &unum);
  1493.  
  1494.   if (nconv < 1)
  1495.   {
  1496.     PRINT_PROGNAME;
  1497.     fprintf (stderr, "(xferoct) : DTL FILE ERROR :  %s \"%s\".\n",
  1498.       "octal number expected, not", token);
  1499.     dexit (1);
  1500.   }
  1501.  
  1502.   putunsigned (n, unum, dvi);
  1503.  
  1504.   return unum;
  1505. }
  1506. /* xferoct */
  1507.  
  1508.  
  1509. U4
  1510. xferunsigned
  1511. #ifdef __STDC__
  1512.   (int n, FILE * dtl, FILE * dvi)
  1513. #else
  1514.   (n, dtl, dvi)
  1515.   int n;
  1516.   FILE * dtl;
  1517.   FILE * dvi;
  1518. #endif
  1519. /* translate unsigned n-byte number from dtl to dvi file. */
  1520. /* return value of unsigned number */
  1521. {
  1522.   U4 unum = 0;  /* at most this space needed */
  1523.  
  1524.   unum = getunsigned (dtl);
  1525.   putunsigned (n, unum, dvi);
  1526.  
  1527.   return unum;
  1528. }
  1529. /* xferunsigned */
  1530.  
  1531. S4
  1532. xfersigned
  1533. #ifdef __STDC__
  1534.   (int n, FILE * dtl, FILE * dvi)
  1535. #else
  1536.   (n, dtl, dvi)
  1537.   int n;
  1538.   FILE * dtl;
  1539.   FILE * dvi;
  1540. #endif
  1541. /* translate signed n-byte number from dtl to dvi file. */
  1542. /* return value of signed number */
  1543. {
  1544.   S4 snum = 0;
  1545.  
  1546.   snum = getsigned (dtl);
  1547.   putsigned (n, snum, dvi);
  1548.  
  1549.   return snum;
  1550. }
  1551. /* xfersigned */
  1552.  
  1553. U4
  1554. getunsigned
  1555. #ifdef __STDC__
  1556.   (FILE * dtl)
  1557. #else
  1558.   (dtl)
  1559.   FILE * dtl;
  1560. #endif
  1561. /* read unsigned number from dtl file. */
  1562. /* return value of unsigned number */
  1563. {
  1564.   U4 unum = 0;  /* at most this space needed */
  1565.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  1566.   int nconv = 0;  /* number of arguments converted by sscanf */
  1567.   Token token = "";  /* DTL token */
  1568.  
  1569.   nread =
  1570.   read_token (dtl, token);
  1571.  
  1572.   nconv = sscanf (token, UF4, &unum);
  1573.  
  1574.   if (nconv < 1)
  1575.   {
  1576.     PRINT_PROGNAME;
  1577.     fprintf (stderr, "(getunsigned) : DTL FILE ERROR :  %s \"%s\".\n",
  1578.       "unsigned number expected, not", token);
  1579.     dexit (1);
  1580.   }
  1581.  
  1582.   return unum;
  1583. }
  1584. /* getunsigned */
  1585.  
  1586. S4
  1587. getsigned
  1588. #ifdef __STDC__
  1589.   (FILE * dtl)
  1590. #else
  1591.   (dtl)
  1592.   FILE * dtl;
  1593. #endif
  1594. /* read signed number from dtl file. */
  1595. /* return value of signed number */
  1596. {
  1597.   S4 snum = 0;
  1598.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  1599.   int nconv = 0;  /* number of sscanf arguments converted and assigned */
  1600.   Token token = "";
  1601.  
  1602.   nread =
  1603.   read_token (dtl, token);
  1604.  
  1605.   nconv = sscanf (token, SF4, &snum);
  1606.  
  1607.   if (nconv < 1)
  1608.   {
  1609.     PRINT_PROGNAME;
  1610.     fprintf (stderr, "(getsigned) : DTL FILE ERROR :  %s \"%s\".\n",
  1611.       "signed number expected, not", token);
  1612.     dexit (1);
  1613.   }
  1614.  
  1615.   return snum;
  1616. }
  1617. /* getsigned */
  1618.  
  1619. int
  1620. putunsigned
  1621. #ifdef __STDC__
  1622.   (int n, U4 unum, FILE * dvi)
  1623. #else
  1624.   (n, unum, dvi)
  1625.   int n;
  1626.   U4 unum;
  1627.   FILE * dvi;
  1628. #endif
  1629. /* put unsigned in-byte integer to dvi file */
  1630. /* DVI format uses Big-endian storage of numbers: */
  1631. /* most significant byte is first. */
  1632. /* return number of bytes written. */
  1633. {
  1634.   Byte ubyte[4];  /* at most 4 bytes needed in DVI format */
  1635.   int i;
  1636.  
  1637.   if (n < 1 || n > 4)
  1638.   {
  1639.     PRINT_PROGNAME;
  1640.     fprintf (stderr,
  1641.       "(putunsigned) : INTERNAL ERROR : asked for %d bytes.  Must be 1 to 4.\n",
  1642.       n);
  1643.     dexit (1);
  1644.   }
  1645.  
  1646.   /* Big-endian storage. */
  1647.   for (i = 0; i < n; i++)
  1648.   {
  1649.     ubyte[i] = (Byte) (unum % 256);
  1650.     unum /= 256;
  1651.   }
  1652.   /* Reverse order for big-endian representation. */
  1653.   for (i = n-1;  i >= 0;  i--)
  1654.   {
  1655.     putbyte (dvi, (int) ubyte[i]);
  1656.   }
  1657.  
  1658.   return n;
  1659. }
  1660. /* putunsigned */
  1661.  
  1662. int
  1663. putsigned
  1664. #ifdef __STDC__
  1665.   (int n, S4 snum, FILE * dvi)
  1666. #else
  1667.   (n, snum, dvi)
  1668.   int n;
  1669.   S4 snum;
  1670.   FILE * dvi;
  1671. #endif
  1672. /* put signed in-byte integer to dvi file */
  1673. /* DVI format uses 2's complement Big-endian storage of signed numbers: */
  1674. /* most significant byte is first. */
  1675. /* return number of bytes written. */
  1676. {
  1677.   /* Will this deal properly with the sign? */
  1678.  
  1679.   if (n < 1 || n > 4)
  1680.   {
  1681.     PRINT_PROGNAME;
  1682.     fprintf (stderr,
  1683.       "(putsigned) : INTERNAL ERROR : asked for %d bytes.  Must be 1 to 4.\n",
  1684.       n);
  1685.     dexit (1);
  1686.   }
  1687.  
  1688.   /* How do we ensure 2's complement representation? */
  1689.   /* Here's a trick that I hope is portable, given ANSI C. */
  1690.   /* See K&R (2nd edition), Appendix A6.2 "Integral Conversions". */
  1691.  
  1692.   /* Convert snum to U4 data type */
  1693.   putunsigned (n, (U4) snum, dvi);
  1694.  
  1695.   return n;
  1696. }
  1697. /* putsigned */
  1698.  
  1699.  
  1700. U4
  1701. xferstring
  1702. #ifdef __STDC__
  1703.   (FILE * dtl, FILE * dvi)
  1704. #else
  1705.   (dtl, dvi)
  1706.   FILE * dtl;
  1707.   FILE * dvi;
  1708. #endif
  1709. /* transfer a string from dtl to dvi file, */
  1710. /* return number of bytes written to dvi file. */
  1711. {
  1712.   U4 n;
  1713.  
  1714.   check_bmes (dtl);
  1715.  
  1716.   if (debug)
  1717.   {
  1718.     PRINT_PROGNAME;
  1719.     fprintf (stderr,
  1720.       "(xferstring) : string is: \"");
  1721.   }
  1722.  
  1723.   for (n=0; ; n++)
  1724.   {
  1725.     int ch;
  1726.  
  1727.     if (read_char (dtl, &ch) == 0)
  1728.     {
  1729.       /* end of dtl file, or reading error */
  1730.       fprintf (stderr, "\n");
  1731.       PRINT_PROGNAME;
  1732.       fprintf (stderr, "(xferstring) : DTL FILE ERROR : cannot read string[");
  1733.       fprintf (stderr, UF4, n);
  1734.       fprintf (stderr, "] from dtl file.\n");
  1735.       dexit (1);
  1736.     }
  1737.  
  1738.     if (debug)
  1739.     {
  1740.       fprintf (stderr, "%c", ch);
  1741.     }
  1742.  
  1743.     if (ch == EMES_CHAR)
  1744.     {
  1745.       (Void) unread_char ();
  1746.       break;
  1747.     }
  1748.     else
  1749.     {
  1750.       putbyte (dvi, ch);
  1751.     }
  1752.   }
  1753.   /* end for */
  1754.  
  1755.   if (debug)
  1756.   {
  1757.     fprintf (stderr, "\".\n");
  1758.   }
  1759.  
  1760.   check_emes (dtl);
  1761.  
  1762.   return n;
  1763. }
  1764. /* xferstring */
  1765.  
  1766.  
  1767. U4
  1768. xferlenstring
  1769. #ifdef __STDC__
  1770.   (int n, FILE * dtl, FILE * dvi)
  1771. #else
  1772.   (n, dtl, dvi)
  1773.   int n;
  1774.   FILE * dtl;
  1775.   FILE * dvi;
  1776. #endif
  1777. /* transfer (length and) quoted string from dtl to dvi file, */
  1778. /* return number of bytes written to dvi file. */
  1779. {
  1780.   U4 k, k2;
  1781.  
  1782.   if (debug)
  1783.   {
  1784.     PRINT_PROGNAME;
  1785.     fprintf (stderr, "(xferlenstring) : about to transfer string.\n");
  1786.   }
  1787.  
  1788.   save_dvi_loc (0);
  1789.  
  1790.   /* k[n] : length of special string */
  1791.  
  1792.   /* If DTL file has been edited, then this length may be wrongly recorded, */
  1793.   /* but later we'll come back to here in the DVI file and fix it */
  1794.  
  1795.   k = xferunsigned (n, dtl, dvi);
  1796.  
  1797.   if (debug)
  1798.   {
  1799.     PRINT_PROGNAME;
  1800.     fprintf (stderr, "(xferlenstring) : string's nominal length k = ");
  1801.     fprintf (stderr, UF4, k);
  1802.     fprintf (stderr, " characters.\n");
  1803.   }
  1804.  
  1805.   /* x[k] : special string */
  1806.   k2 = xferstring (dtl, dvi);
  1807.  
  1808.   save_dvi_loc (1);
  1809.  
  1810.   if (k2 != k)
  1811.   {
  1812.     PRINT_PROGNAME;
  1813.     fprintf (stderr, "(special) : WARNING : string length (");
  1814.     fprintf (stderr, UF4, k);
  1815.     fprintf (stderr, ") in DTL file is wrong\n");
  1816.     fprintf (stderr, "Writing correct value (");
  1817.     fprintf (stderr, UF4, k2);
  1818.     fprintf (stderr, ") to DVI file\n");
  1819.  
  1820.     restore_dvi_loc (0);
  1821.     -- dvi_written;
  1822.     putunsigned (n, k2, dvi);
  1823.     restore_dvi_loc (1);
  1824.   }
  1825.  
  1826.   return (n + k2);
  1827. }
  1828. /* xferlenstring */
  1829.  
  1830. int save_dvi_loc
  1831. #ifdef __STDC__
  1832.   (int ln)
  1833. #else
  1834.   (ln)
  1835.   int ln;
  1836. #endif
  1837. {
  1838.   if (ln < 0 || ln >= NLOCS)
  1839.   {
  1840.     PRINT_PROGNAME;
  1841.     fprintf (stderr,
  1842.       "(save_dvi_loc) : INTERNAL ERROR : bad loc number %d, ", ln);
  1843.     fprintf (stderr, "must be between 0 and %d\n", NLOCS-1);
  1844.     dexit (1);
  1845.   }
  1846.  
  1847.   dvi_loc[ln] = ftell (dvi);
  1848.   if (dvi_loc[ln] == -1L)
  1849.   {
  1850.     PRINT_PROGNAME;
  1851.     fprintf (stderr, "(save_dvi_loc) : DVI FILE ERROR : error on ftell");
  1852.     fprintf (stderr, "\n");
  1853.     dexit (1);
  1854.   }
  1855.  
  1856.   return 0;  /* success */
  1857. }
  1858. /* save_dvi_loc */
  1859.  
  1860. int restore_dvi_loc
  1861. #ifdef __STDC__
  1862.   (int ln)
  1863. #else
  1864.   (ln)
  1865.   int ln;
  1866. #endif
  1867. {
  1868.   if (ln < 0 || ln >= NLOCS)
  1869.   {
  1870.     PRINT_PROGNAME;
  1871.     fprintf (stderr,
  1872.       "(restore_dvi_loc) : INTERNAL ERROR : bad loc number %d, ", ln);
  1873.     fprintf (stderr, "must be between 0 and %d\n", NLOCS-1);
  1874.     dexit (1);
  1875.   }
  1876.  
  1877.   if (fseek (dvi, dvi_loc[ln], FILE_BEGIN) != 0)
  1878.   {
  1879.     PRINT_PROGNAME;
  1880.     fprintf (stderr, "(restore_dvi_loc) : DVI FILE ERROR : error on fseek");
  1881.     fprintf (stderr, " when DVI offset = %ld", dvi_loc[ln]);
  1882.     fprintf (stderr, "\n");
  1883.     dexit (1);
  1884.   }
  1885.  
  1886.   return 0;  /* success */
  1887. }
  1888. /* restore_dvi_loc */
  1889.  
  1890.  
  1891. S4
  1892. xfer_bop_address
  1893. #ifdef __STDC__
  1894.   (FILE * dtl, FILE * dvi)
  1895. #else
  1896.   (dtl, dvi)
  1897.   FILE * dtl;
  1898.   FILE * dvi;
  1899. #endif
  1900. /* translate signed 4-byte bop address from dtl to dvi file. */
  1901. /* return value of bop address written to DVI file */
  1902. {
  1903.   S4 snum = 0;  /* at most this space needed for byte address */
  1904.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  1905.   int nconv = 0;  /* number of arguments converted by sscanf */
  1906.   Token token = "";  /* DTL token */
  1907.  
  1908.   nread +=
  1909.   read_token (dtl, token);
  1910.  
  1911.   nconv = sscanf (token, SF4, &snum);
  1912.  
  1913.   if (nconv != 1)
  1914.   {
  1915.     PRINT_PROGNAME;
  1916.     fprintf (stderr, "(xfer_bop_address) : DTL FILE ERROR :  %s \"%s\".\n",
  1917.       "signed number expected, not", token);
  1918.     dexit (1);
  1919.   }
  1920.  
  1921.   if (snum != last_bop_address)
  1922.   {
  1923.     PRINT_PROGNAME;
  1924.     fprintf (stderr, "(xfer_bop_address) : WARNING : byte address (");
  1925.     fprintf (stderr, WF, snum);
  1926.     fprintf (stderr, ")\n");
  1927.     fprintf (stderr, "for previous bop in DTL file is wrong\n");
  1928.     fprintf (stderr, "Writing correct value (");
  1929.     fprintf (stderr, WF, last_bop_address);
  1930.     fprintf (stderr, ") to DVI file\n");
  1931.   }
  1932.  
  1933.   putsigned (4, last_bop_address, dvi);
  1934.  
  1935.   return last_bop_address;
  1936. }
  1937. /* xfer_bop_address */
  1938.  
  1939.  
  1940. S4
  1941. xfer_postamble_address
  1942. #ifdef __STDC__
  1943.   (FILE * dtl, FILE * dvi)
  1944. #else
  1945.   (dtl, dvi)
  1946.   FILE * dtl;
  1947.   FILE * dvi;
  1948. #endif
  1949. /* translate signed 4-byte postamble address from dtl to dvi file. */
  1950. /* return value of postamble address written to DVI file */
  1951. {
  1952.   S4 snum = 0;  /* at most this space needed for byte address */
  1953.   COUNT nread = 0;  /* number of DTL bytes read by read_token */
  1954.   int nconv = 0;  /* number of arguments converted by sscanf */
  1955.   Token token = "";  /* DTL token */
  1956.  
  1957.   nread +=
  1958.   read_token (dtl, token);
  1959.  
  1960.   nconv = sscanf (token, SF4, &snum);
  1961.  
  1962.   if (nconv != 1)
  1963.   {
  1964.     PRINT_PROGNAME;
  1965.     fprintf (stderr, "(xfer_postamble_address) : DTL FILE ERROR :  ");
  1966.     fprintf (stderr, "signed number expected, not \"%s\".\n", token);
  1967.     dexit (1);
  1968.   }
  1969.  
  1970.   if (snum != postamble_address)
  1971.   {
  1972.     PRINT_PROGNAME;
  1973.     fprintf (stderr, "(xfer_postamble_address) : WARNING : byte address (");
  1974.     fprintf (stderr, WF, snum);
  1975.     fprintf (stderr, ")\n");
  1976.     fprintf (stderr, "for postamble in DTL file is wrong\n");
  1977.     fprintf (stderr, "Writing correct value (");
  1978.     fprintf (stderr, WF, postamble_address);
  1979.     fprintf (stderr, ") to DVI file\n");
  1980.   }
  1981.  
  1982.   putsigned (4, postamble_address, dvi);
  1983.  
  1984.   return postamble_address;
  1985. }
  1986. /* xfer_postamble_address */
  1987.  
  1988.  
  1989. int
  1990. puttable
  1991. #ifdef __STDC__
  1992.   (op_table table, int opcode, FILE * dtl, FILE * dvi)
  1993. #else
  1994.   (table, opcode, dtl, dvi)
  1995.   op_table table;
  1996.   int opcode;
  1997.   FILE * dtl;
  1998.   FILE * dvi;
  1999. #endif
  2000. {
  2001.   /* table:  {char * name; int first, last; op_info * list; }; */
  2002.   /* op_info:   {int code; char * name; int nargs; char * args; }; */
  2003.  
  2004.   op_info op;  /* entry in table */
  2005.   int i;
  2006.   int pos;  /* current position in string being scanned */
  2007.   String args = "";
  2008.  
  2009.   /* Defensive programming. */
  2010.   if (opcode < table.first || opcode > table.last)
  2011.   {
  2012.     PRINT_PROGNAME;
  2013.     fprintf (stderr,
  2014.       "(puttable) : DTL FILE (OR INTERNAL) ERROR : opcode %d ", opcode);
  2015.     fprintf (stderr, "is outside table %s [ %d to %d ] !\n",
  2016.       table.name, table.first, table.last);
  2017.     dexit (1);
  2018.   }
  2019.  
  2020.   op = table.list [ opcode - table.first ];
  2021.  
  2022.   /* More defensive programming. */
  2023.   if (opcode != op.code)
  2024.   {
  2025.     PRINT_PROGNAME;
  2026.     fprintf (stderr,
  2027.       "(puttable) : INTERNAL ERROR : opcode %d for command \"%s\" %s \"%s\".\n",
  2028.       opcode, op.name, "faulty in table", table.name);
  2029.     dexit (1);
  2030.   }
  2031.  
  2032.   /* process all the arguments, according to size and sign */
  2033.  
  2034.   strncpy (args, op.args, MAXSTRLEN);
  2035.  
  2036.   pos = 0;
  2037.   for (i=0; i < op.nargs; i++)
  2038.   {
  2039.     int argtype = 0;
  2040.     int nscan = 0;  /* number of bytes read by sscanf */
  2041.     int nconv = 0;  /* number of sscanf arguments converted & assigned */
  2042.  
  2043.     /* sscanf() does NOT advance over its input: */
  2044.     /* C strings lack internal state information, which C files have. */
  2045.     /* On Sun/OS, sscanf calls ungetc on the string it reads, */
  2046.     /* which therefore has to be writable. */
  2047.  
  2048.     nconv = sscanf (args + pos, "%d%n", &argtype, &nscan);
  2049.  
  2050.     if (nconv < 1 || nscan < 1)
  2051.     {
  2052.       PRINT_PROGNAME;
  2053.       fprintf (stderr,
  2054.         "(puttable) : INTERNAL ERROR : internal read of table %s failed!\n",
  2055.         table.name);
  2056.       dexit (1);
  2057.     }
  2058.  
  2059.     pos += nscan;
  2060.  
  2061.     if (argtype < 0)
  2062.       xfersigned (-argtype, dtl, dvi);
  2063.     else
  2064.       xferunsigned (argtype, dtl, dvi);
  2065.   }
  2066.   /* end for */
  2067.  
  2068.   return 1;  /* OK */
  2069. }
  2070. /* puttable */
  2071.  
  2072.  
  2073. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  2074. U4
  2075. special
  2076. #ifdef __STDC__
  2077.   (FILE * dtl,  FILE * dvi,  int n)
  2078. #else
  2079.   (dtl,  dvi,  n)
  2080.   FILE * dtl;
  2081.   FILE * dvi;
  2082.   int n;
  2083. #endif
  2084. /* read special (1 <= n <= 4 byte) data from dtl, and write in dvi */
  2085. /* return number of bytes written */
  2086. {
  2087.   U4  nk;
  2088.  
  2089.   if (n < 1 || n > 4)
  2090.   {
  2091.     PRINT_PROGNAME;
  2092.     fprintf (stderr, "(special) : DTL FILE ERROR : special %d, ", n);
  2093.     fprintf (stderr, "range is 1 to 4.\n");
  2094.     dexit (1);
  2095.   }
  2096.  
  2097.   /* k[n] : length of special string */
  2098.   /* x[k] : special string */
  2099.   /* nk = n + k */
  2100.   nk = xferlenstring (n, dtl, dvi);
  2101.  
  2102.   return (nk);
  2103. }
  2104. /* special */
  2105.  
  2106. int
  2107. check_bmes
  2108. #ifdef __STDC__
  2109.   (FILE * dtl)
  2110. #else
  2111.   (dtl)
  2112.   FILE * dtl;
  2113. #endif
  2114. /* check that a BMES_CHAR is the next non-whitespace character in dtl */
  2115. {
  2116.   int ch;  /* next non-whitespace character in dtl */
  2117.  
  2118.   /* ignore number of spaces skipped */
  2119.   (Void) skip_space (dtl, &ch);
  2120.  
  2121.   if (ch < 0)
  2122.   {
  2123.     PRINT_PROGNAME;
  2124.     fprintf (stderr,
  2125.       "(check_bmes) : DTL FILE ERROR : end of dtl file, or reading error\n");
  2126.     dexit (1);
  2127.   }
  2128.  
  2129.   if (ch != BMES_CHAR)
  2130.   {
  2131.     PRINT_PROGNAME;
  2132.     fprintf (stderr,
  2133.       "(check_bmes) : DTL FILE ERROR : '%c' %s, not '%c' (%d).\n",
  2134.       BMES_CHAR, "expected to precede string", ch, ch);
  2135.     dexit (1);
  2136.   }
  2137.  
  2138.   return 1;  /* OK */
  2139. }
  2140. /* check_bmes */
  2141.  
  2142. int
  2143. check_emes
  2144. #ifdef __STDC__
  2145.   (FILE * dtl)
  2146. #else
  2147.   (dtl)
  2148.   FILE * dtl;
  2149. #endif
  2150. /* check that an EMES_CHAR is the next character in dtl */
  2151. {
  2152.   int ch;  /* dtl character */
  2153.  
  2154.   if (read_char (dtl, &ch) == 0)
  2155.   {
  2156.     PRINT_PROGNAME;
  2157.     fprintf (stderr,
  2158.       "(check_emes) : DTL FILE ERROR : end of dtl file, or reading error\n");
  2159.     dexit (1);
  2160.   }
  2161.  
  2162.   if (ch != EMES_CHAR)
  2163.   {
  2164.     PRINT_PROGNAME;
  2165.     fprintf (stderr,
  2166.       "(check_emes) : DTL FILE ERROR : '%c' %s, not '%c' (%d).\n",
  2167.       EMES_CHAR, "expected to follow string", ch, ch);
  2168.     dexit (1);
  2169.   }
  2170.  
  2171.   return 1;  /* OK */
  2172. }
  2173. /* check_emes */
  2174.  
  2175. int
  2176. fontdef
  2177. #ifdef __STDC__
  2178.   (FILE * dtl,  FILE * dvi,  int s)
  2179. #else
  2180.   (dtl,  dvi,  s)
  2181.   FILE * dtl;
  2182.   FILE * dvi;
  2183.   int s;
  2184. #endif
  2185. /* read fontdef fnt_def1 .. fnt_def4 from dtl, and write in dvi */
  2186. /* s is the fontdef suffix : 1 to 4 */
  2187. /* return number of bytes written */
  2188. {
  2189.   U4  a, l, al;
  2190.   U4 k;
  2191.  
  2192.   if (s < 1 || s > 4)
  2193.   {
  2194.     PRINT_PROGNAME;
  2195.     fprintf (stderr,
  2196.       "(fontdef) : DTL FILE ERROR : font def %d, but range is 1 to 4.\n", s);
  2197.     dexit (1);
  2198.   }
  2199.  
  2200.   if (debug)
  2201.   {
  2202.     PRINT_PROGNAME;
  2203.     fprintf (stderr, "(fontdef) : about to read font number.\n");
  2204.   }
  2205.  
  2206.   /* k[s] : font number */
  2207.   if (s == 4)
  2208.     k = xfersigned (s, dtl, dvi);
  2209.   else
  2210.     k = xferunsigned (s, dtl, dvi);
  2211.  
  2212.   if (debug)
  2213.   {
  2214.     PRINT_PROGNAME;
  2215.     fprintf (stderr, "(fontdef) : font ");
  2216.     fprintf (stderr, UF4, k);
  2217.     fprintf (stderr, ".\n");
  2218.   }
  2219.  
  2220. #ifdef HEX_CHECKSUM
  2221.   /* c[4] : (hexadecimal) checksum : I (gt) would prefer this */
  2222.   xferhex (4, dtl, dvi);
  2223. #else
  2224.   /* c[4] : checksum (octal, for quick comparison with tftopl's .pl file) */
  2225.   xferoct (4, dtl, dvi);
  2226. #endif
  2227.  
  2228.   /* s[4] */
  2229.   xferunsigned (4, dtl, dvi);
  2230.  
  2231.   /* d[4] */
  2232.   xferunsigned (4, dtl, dvi);
  2233.  
  2234.   /* a[1] : length of font `area' (directory) portion of pathname string */
  2235.   a = xferunsigned (1, dtl, dvi);
  2236.  
  2237.   /* l[1] : length of font filename portion of pathname string */
  2238.   l = xferunsigned (1, dtl, dvi);
  2239.  
  2240.   /* n[a+l] : font pathname string */
  2241.   /* al = a+l */
  2242.   al = xferstring (dtl, dvi);
  2243.  
  2244.   if (al != a + l)
  2245.   {
  2246.     PRINT_PROGNAME;
  2247.     fprintf (stderr,
  2248.       "(fontdef) : DTL FILE ERROR : Inconsistent length for font pathname:\n");
  2249.     fprintf (stderr, "Recorded as ");
  2250.     fprintf (stderr, UF4, a);
  2251.     fprintf (stderr, " + ");
  2252.     fprintf (stderr, UF4, l);
  2253.     fprintf (stderr, " = ");
  2254.     fprintf (stderr, UF4, a+l);
  2255.     fprintf (stderr, ", but measured as ");
  2256.     fprintf (stderr, UF4, al);
  2257.     fprintf (stderr, "\n");
  2258.     dexit (1);
  2259.   }
  2260.  
  2261.   return (s + 4*4 + 2*1 + al);
  2262. }
  2263. /* fontdef */
  2264.  
  2265. U4
  2266. preamble
  2267. #ifdef __STDC__
  2268.   (FILE * dtl,  FILE * dvi)
  2269. #else
  2270.   (dtl,  dvi)
  2271.   FILE * dtl;
  2272.   FILE * dvi;
  2273. #endif
  2274. /* read preamble from dtl, and write in dvi */
  2275. /* return number of bytes written */
  2276. {
  2277.   U4  k1;
  2278.  
  2279.   /* i[1] */
  2280.   xferunsigned (1, dtl, dvi);
  2281.  
  2282.   /* num[4] */
  2283.   xferunsigned (4, dtl, dvi);
  2284.  
  2285.   /* den[4] */
  2286.   xferunsigned (4, dtl, dvi);
  2287.  
  2288.   /* mag[4] */
  2289.   xferunsigned (4, dtl, dvi);
  2290.  
  2291.   /* k[1] : length of comment */
  2292.   /* x[k] : comment string */
  2293.   /* k1 = 1 + k */
  2294.   k1 = xferlenstring (1, dtl, dvi);
  2295.  
  2296.   return (1 + 3*4 + k1);
  2297. }
  2298. /* preamble */
  2299.  
  2300. int
  2301. postamble
  2302. #ifdef __STDC__
  2303.   (FILE * dtl,  FILE * dvi)
  2304. #else
  2305.   (dtl,  dvi)
  2306.   FILE * dtl;
  2307.   FILE * dvi;
  2308. #endif
  2309. /* read postamble from dtl, and write in dvi */
  2310. /* return number of bytes written */
  2311. {
  2312.   postamble_address = dvi_written - 1;
  2313.  
  2314.   /* p[4] : DVI address of previous bop command */
  2315.   /*        --- unsigned? --- or signed, as I assume? */
  2316.   /* For, surely  p  should be  -1  if the DVI file has NO bop? */
  2317.   xfer_bop_address (dtl, dvi);
  2318.  
  2319.   /* num[4] */
  2320.   xferunsigned (4, dtl, dvi);
  2321.  
  2322.   /* den[4] */
  2323.   xferunsigned (4, dtl, dvi);
  2324.  
  2325.   /* mag[4] */
  2326.   xferunsigned (4, dtl, dvi);
  2327.  
  2328.   /* l[4] */
  2329.   xferunsigned (4, dtl, dvi);
  2330.  
  2331.   /* u[4] */
  2332.   xferunsigned (4, dtl, dvi);
  2333.  
  2334.   /* s[2] */
  2335.   xferunsigned (2, dtl, dvi);
  2336.  
  2337.   /* t[2] */
  2338.   xferunsigned (2, dtl, dvi);
  2339.  
  2340.   return (6*4 + 2*2);
  2341. }
  2342. /* postamble */
  2343.  
  2344. int
  2345. post_post
  2346. #ifdef __STDC__
  2347.   (FILE * dtl,  FILE * dvi)
  2348. #else
  2349.   (dtl,  dvi)
  2350.   FILE * dtl;
  2351.   FILE * dvi;
  2352. #endif
  2353. /* read post_post from dtl, and write in dvi */
  2354. /* return number of bytes written */
  2355. {
  2356.   /* hope I'm writing the "223" bytes in an 8-bit clean way */
  2357.   int n223;  /* number of "223" bytes in final padding */
  2358.  
  2359.   /* q[4] : DVI address of post command */
  2360.   /*        --- unsigned? --- or signed, as I assume? */
  2361.   /* what happens if there is NO postamble command? */
  2362.   /* shouldn't  q  be  -1  then? */
  2363.  
  2364.   xfer_postamble_address (dtl, dvi);
  2365.  
  2366.   /* i[1] : DVI identification byte = 2 */
  2367.   xferunsigned (1, dtl, dvi);
  2368.  
  2369.   /* final padding of DVI file by "223" bytes to a multiple of 4 bytes */
  2370.  
  2371.   for (n223 = 0;  true;  n223++)
  2372.   {
  2373.     COUNT nread = 0;  /* number of DTL bytes read by read_token */
  2374.     Token token = "";
  2375.  
  2376.     nread =
  2377.     read_token (dtl, token);
  2378.  
  2379.     /* check whether end of dtl file */
  2380.     if (nread == 0)
  2381.     {
  2382.       if (group)
  2383.       {
  2384.     /* dtl file shouldn't end before an ECOM */
  2385.         PRINT_PROGNAME;
  2386.     fprintf (stderr,
  2387.       "(post_post) : DTL FILE ERROR : premature end of DTL file!\n");
  2388.     fprintf (stderr,
  2389.       "%d complete iterations of \"padding byte\" loop \n",
  2390.       n223);
  2391.     fprintf (stderr,
  2392.       "troublesome token = \"%s\"\n",
  2393.       token);
  2394.     dexit (1);
  2395.       }
  2396.       /* leave the "223" loop */
  2397.       break;
  2398.     }
  2399.     else if (strcmp (token, "223") == 0)
  2400.     {
  2401.       /* token is a "223" padding byte */
  2402.       putbyte (dvi, 223);
  2403.       /* loop again */
  2404.     }
  2405.     else
  2406.     {
  2407.       /* read a non-empty token that wasn't "223" */
  2408.       (Void) unread_char ();
  2409.       if (group)
  2410.       {
  2411.     if (strcmp (token, ECOM) == 0)
  2412.     {
  2413.       /* end of post_post */
  2414.     }
  2415.     else
  2416.     {
  2417.       /* error : expected end of post_post */
  2418.           PRINT_PROGNAME;
  2419.       fprintf (stderr, "(post_post) : DTL FILE ERROR : ");
  2420.       fprintf (stderr, "token \"%s\" should be \"%s\"\n", token, ECOM);
  2421.       dexit (1);
  2422.     }
  2423.       }
  2424.       /* leave the "223" loop */
  2425.       break;
  2426.     }
  2427.   }
  2428.   /* end for */
  2429.  
  2430.   if (n223 < 4)
  2431.   {
  2432.     PRINT_PROGNAME;
  2433.     fprintf (stderr, "(post_post) : DTL FILE ERROR : bad post_post:  ");
  2434.     fprintf (stderr, "fewer than four `223' bytes.\n");
  2435.     dexit (1);
  2436.   }
  2437.  
  2438.   /* check whether the DVI file size is a multiple of 4 bytes */
  2439.   if (dvi_written % 4 != 0)
  2440.   {
  2441.     PRINT_PROGNAME;
  2442.     fprintf (stderr, "(post_post) : DTL FILE (OR INTERNAL) ERROR : ");
  2443.     fprintf (stderr, "DVI size ");
  2444.     fprintf (stderr, WF, dvi_written);
  2445.     fprintf (stderr, " (bytes) isn't a multiple of 4 !\n");
  2446.     dexit (1);
  2447.   }
  2448.  
  2449.   return (4 + 1 + n223);
  2450. }
  2451. /* post_post */
  2452.  
  2453. Void
  2454. dinfo (VOID)
  2455. {
  2456.   PRINT_PROGNAME;
  2457.   fprintf (stderr, "(dinfo) : ");
  2458.   fprintf (stderr, "Current DTL input line:\n");
  2459.   fprintf (stderr, "\"%s\"\n", dtl_line.buf);
  2460.   fprintf (stderr, "Read ");
  2461.   fprintf (stderr, WF, dtl_read);
  2462.   fprintf (stderr, " DTL bytes (");
  2463.   fprintf (stderr, WF, com_read);
  2464.   fprintf (stderr, " in current command), wrote ");
  2465.   fprintf (stderr, WF, dvi_written);
  2466.   fprintf (stderr, " DVI bytes.\n");
  2467.   fprintf (stderr, "Successfully interpreted ");
  2468.   fprintf (stderr, WF, ncom);
  2469.   fprintf (stderr, " DVI command%s.\n", (ncom == 1 ? "" : "s"));
  2470. }
  2471. /* dinfo */
  2472.  
  2473. Void
  2474. dexit
  2475. #ifdef __STDC__
  2476.   (int n)
  2477. #else
  2478.   (n)
  2479.   int n;
  2480. #endif
  2481. {
  2482.   dinfo();
  2483.   PRINT_PROGNAME;
  2484.   fprintf (stderr, "(dexit) : exiting with status %d.\n", n);
  2485.   exit (n);
  2486. }
  2487. /* dexit */
  2488.  
  2489. /* end of dt2dv.c */
  2490.